<!--
 * @Author: ssj
 * @Date: 2021-08-16 10:25:16
 * @LastEditors: swc
 * @LastEditTime: 2024-08-30 09:37:55
 * @Description: oImageSelector
 *
-->
<template>
  <div class="o-file-input">
    <div class="o-file-box">
      <div class="file-container" v-for="(el, idx) in lValue" :key="idx">
        <i
          v-if="el._content_ === 'file'"
          class="wy-icon"
          :title="el.fileName"
          :class="[el.class, { 'file-chked': el.checked }]"
          @click.stop="fileCheck(idx, $event)"
        ></i>
      </div>
    </div>

    <div class="o-file-btn" @click="downLoadFile">
      <i class="wy-icon wy-download"></i>
    </div>
  </div>
</template>
<script lang="ts">
import { T_srv, ts, Tsrv, vue } from '@/services';
import { N_input } from '@/types';

interface I_value extends N_input.I_fileDesc {
  class: string;
  checked: boolean;
}
@T_srv.comp
export default class oFileInputCell extends vue {
  @T_srv.prop() renderOpts: N_input.I_renderOpts;

  @T_srv.prop() params: any;

  public G_compName: string = 'oFileInputCell';

  private G_value: N_input.I_fileValue = {
    fileLibID: '',
    files: []
  };

  // 内部渲染
  private lValue: Array<I_value> = [];

  // value
  private G_paramsFromComp: 'oBaseGrid' | 'oBaseForm' = null;

  private G_funName: string = '';

  private suffixClass: Map<string, string> = new Map();

  private fileClass: Map<string, Set<string>> = new Map([
    [
      'text',
      new Set(['.txt', '.rtf', '.md', '.doc', '.docx', '.pdf', '.htm', '.html'])
    ],
    ['sheet', new Set(['.xls', '.xlsx'])],
    [
      'video',
      new Set([
        '.avi',
        '.wmv',
        '.mpg',
        '.mpeg',
        '.mov',
        '.rm',
        '.ram',
        '.swf',
        '.flv',
        '.mp4',
        '.mkv',
        '.rmvb'
      ])
    ],
    [
      'audio',
      new Set(['.mp3', '.wav', '.aac', '.flac', '.m4a', '.mid', '.ape', '.ogg'])
    ],
    [
      'image',
      new Set([
        '.jpg',
        '.jpeg',
        '.png',
        '.gif',
        '.bmp',
        '.psd',
        '.tiff',
        '.webp'
      ])
    ],
    [
      'drawing',
      new Set([
        '.dwg',
        '.dxf',
        '.dwt',
        '.dws',
        '.dxf',
        '.dwf',
        '.3ds',
        '.max',
        '.obj',
        '.fbx',
        '.stl',
        '.rfa',
        '.rte',
        '.rvt',
        '.dgn',
        '.glb'
      ])
    ],
    [
      'unknown',
      new Set([
        '.exe',
        '.lnk',
        '.zip',
        '.rar',
        '.7z',
        '.tar',
        '.iso',
        '.jar',
        '.war',
        '.ear',
        '.hpi',
        '.hpl'
      ])
    ]
  ]);

  @T_srv.watch('params')
  private onParamsChange(): void {
    this.setValue(this.params.row[this.params.column.field]);
  }

  @T_srv.model('model-change') modelvalue: string | null;

  @T_srv.watch('modelvalue')
  private onValueChange(val: string | null): void {
    // this.setValue(val);
  }

  created() {
    if (this.renderOpts.props.getTcommand()?.oBaseGrid?.G_compName) {
      this.G_paramsFromComp = 'oBaseGrid';
    } else if (this.renderOpts.props.getTcommand()?.oBaseForm?.G_compName) {
      this.G_paramsFromComp = 'oBaseForm';
    } else {
      this.$msg({});
      console.error('未定义的组件');
    }
    this.init();
  }

  mounted() {}

  /**
   * @Author: ssj
   * @description: 初始化
   */
  private init(): void {
    this.fileClass.forEach((v, k) => {
      let icon: string = '';
      switch (k) {
        case 'text':
          icon = 'wy-txt';
          break;
        case 'sheet':
          icon = 'wy-file-excel';
          break;

        case 'video':
          icon = 'wy-shipin';
          break;
        case 'audio':
          icon = 'wy-audio';
          break;
        case 'image':
          icon = 'wy-img';
          break;
        case 'drawing':
          icon = 'wy-tuzhi';
          break;
        case 'unknown':
          icon = 'wy-unknownfile';
          break;
        default:
          console.error('不能识别的文件类型定义');
      }
      v.forEach(suffix => {
        this.suffixClass.set(suffix, icon);
      });
    });
    this.G_funName = this.renderOpts.props.funName;
    this.setValue(this.params.row[this.params.column.field]);
  }

  public setValue(val: N_input.I_fileValue | string): void {
    const err = () => {
      this.$msg('-530,FE,90');
      console.error('json表达式不是一个数组');
    };
    this.lValue = [];
    this.G_value = {
      fileLibID: '',
      files: []
    };
    if (typeof val === 'string') {
      try {
        const v: N_input.I_fileValue = JSON.parse(val) || [];
        if (typeof v !== 'object') {
          err();
        }
        this.syncValue(v);
      } catch {
        err();
      }
    } else if (typeof val === 'object') {
      this.syncValue(val);
    } else {
      err();
    }
  }

  private syncValue(val: N_input.I_fileValue) {
    if (Tsrv.noValue(val)) return;
    val.files.forEach(el => {
      if (Tsrv.utils.noValue(this.G_value.fileLibID)) {
        this.G_value.fileLibID = val.fileLibID;
      }
      this.G_value.files.push({
        // 识别此json内容是什么内容
        _content_: el._content_,
        // 文件名
        fileName: el.fileName,
        // 文件库里的文件名
        libFileName: el.libFileName
      });
      const fArr = el.fileName.split(`.`);
      const suffix = fArr.length > 1 ? fArr[fArr.length - 1] : '';
      this.lValue.push({
        // 识别此json内容是什么内容
        _content_: el._content_,
        // 文件名
        fileName: el.fileName,
        // 文件库里的文件名
        libFileName: el.libFileName,
        class: this.suffixClass.get(`.${suffix}`),
        checked: false
      });
    });
  }

  /**
   * @Author: ssj
   * @description: 获取value
   */
  public getValue(): any {
    return this.G_value;
  }

  /**
   * @Author: ssj
   * @param {string} event 发送事件名
   * @description: 发送事件
   */
  public emitEvent(event: string): void {
    const ev: any = this.renderOpts.events;
    const params = Tsrv.utils.cloneNoMatchVue(this.params, true);
    params.from = 'inputtext';
    for (const action in ev) {
      if (ev[action] && action === `on-${event}`) {
        ev[action](params);
      }
    }
    this.$emit('model-change', this.G_value);
    this.$emit('on-change', this.G_value);
  }

  public fileCheck(idx: number, e: any) {
    if (Tsrv.utils.noValue(this.lValue)) {
      return;
    }
    this.lValue.forEach(el => {
      el.checked = false;
    });
    this.lValue[idx].checked = true;
    // 10秒后取消选择
    this.cleanFileSelected();
  }

  public downLoadFile() {
    if (this.lValue.length === 1) {
      this.lValue[0].checked = true;
    } else if (
      this.lValue.length > 1 &&
      this.lValue.filter(ele => ele.checked).length === 0
    ) {
      this.$Message.info('请选择一个文件下载');
    }
    this.lValue.forEach(ele => {
      if (ele.checked) {
        const dwn = new ts.T_downloadArg();
        dwn.setFileName(ele.libFileName).setPath('file');
        Tsrv.download(dwn, true, ele.fileName)
          .then(r => {
            if (r.err) {
              this.$msg(r.err);
            }
          })
          .catch(err => {
            this.$msg(err);
          });
      }
    });
  }

  public getFileSuffix(): string {
    let s: string = '';
    this.fileClass.forEach(el => {
      s = !s ? Array.from(el).join(',') : `${s},${Array.from(el).join(',')}`;
    });
    return s;
  }

  public cleanFileSelected() {
    setTimeout(() => {
      this.lValue.forEach(ele => {
        ele.checked = false;
      });
    }, 10000);
  }
}
</script>

<style scoped lang="scss">
.o-file-input {
  // padding: 3px;
  display: flex;
  align-items: center;
  // height: 40px;
  width: 100%;
  overflow: hidden;
  .o-file-box {
    display: flex;
    height: 100%;
    padding-right: 5px;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    .file-container {
      height: 100%;
      width: 100%;
      display: flex;
      align-items: center;
      > i {
        font-size: 26px;
      }
      .file-chked {
        border: 1px solid red;
      }
    }
  }
  .o-file-btn {
    width: 23px;
    flex-shrink: 0;
    position: relative;
    height: 30px;
    display: flex;
    align-items: center;
    cursor: pointer;
    overflow: hidden;
    > i {
      width: 23px;
      cursor: pointer;
      color: var(--default-hover-font-color);
      font-size: 18px;
    }
    > input[type='file'] {
      width: 23px;
      opacity: 0;
      position: absolute;
      left: 0;
      top: 0;
      cursor: pointer;
    }
  }
}
</style>
